---
title: 构建语音智能体
description: Learn how to build voice agents using the OpenAI Agents SDK, what features are available, how to architecture your application, and more.
---

import { Steps, Aside, Code } from '@astrojs/starlight/components';
import createAgentExample from '../../../../../../../examples/docs/voice-agents/createAgent.ts?raw';
import multiAgentsExample from '../../../../../../../examples/docs/voice-agents/multiAgents.ts?raw';
import createSessionExample from '../../../../../../../examples/docs/voice-agents/createSession.ts?raw';
import configureSessionExample from '../../../../../../../examples/docs/voice-agents/configureSession.ts?raw';
import handleAudioExample from '../../../../../../../examples/docs/voice-agents/handleAudio.ts?raw';
import defineToolExample from '../../../../../../../examples/docs/voice-agents/defineTool.ts?raw';
import toolApprovalEventExample from '../../../../../../../examples/docs/voice-agents/toolApprovalEvent.ts?raw';
import guardrailsExample from '../../../../../../../examples/docs/voice-agents/guardrails.ts?raw';
import guardrailSettingsExample from '../../../../../../../examples/docs/voice-agents/guardrailSettings.ts?raw';
import audioInterruptedExample from '../../../../../../../examples/docs/voice-agents/audioInterrupted.ts?raw';
import sessionInterruptExample from '../../../../../../../examples/docs/voice-agents/sessionInterrupt.ts?raw';
import sessionHistoryExample from '../../../../../../../examples/docs/voice-agents/sessionHistory.ts?raw';
import historyUpdatedExample from '../../../../../../../examples/docs/voice-agents/historyUpdated.ts?raw';
import updateHistoryExample from '../../../../../../../examples/docs/voice-agents/updateHistory.ts?raw';
import customWebRTCTransportExample from '../../../../../../../examples/docs/voice-agents/customWebRTCTransport.ts?raw';
import websocketSessionExample from '../../../../../../../examples/docs/voice-agents/websocketSession.ts?raw';
import transportEventsExample from '../../../../../../../examples/docs/voice-agents/transportEvents.ts?raw';
import thinClientExample from '../../../../../../../examples/docs/voice-agents/thinClient.ts?raw';
import toolHistoryExample from '../../../../../../../examples/docs/voice-agents/toolHistory.ts?raw';
import sendMessageExample from '../../../../../../../examples/docs/voice-agents/sendMessage.ts?raw';
import serverAgentExample from '../../../../../../../examples/docs/voice-agents/serverAgent.ts?raw';
import delegationAgentExample from '../../../../../../../examples/docs/voice-agents/delegationAgent.ts?raw';
import turnDetectionExample from '../../../../../../../examples/docs/voice-agents/turnDetection.ts?raw';

## 音频处理

某些传输层（如默认的 `OpenAIRealtimeWebRTC`）会自动为你处理音频输入与输出。对于其他传输机制（如 `OpenAIRealtimeWebSocket`），你需要自行处理会话音频：

<Code lang="typescript" code={handleAudioExample} />

## 会话配置

你可以在构造时向 [`RealtimeSession`](/openai-agents-js/openai/agents-realtime/classes/realtimesession/) 传入额外选项，或在调用 `connect(...)` 时进行配置。

<Code lang="typescript" code={configureSessionExample} />

这些传输层允许你传递任意与 [session](https://platform.openai.com/docs/api-reference/realtime-client-events/session/update) 匹配的参数。

对于那些新增且在 [RealtimeSessionConfig](/openai-agents-js/openai/agents-realtime/type-aliases/realtimesessionconfig/) 中没有对应参数的设置，你可以使用 `providerData`。传入 `providerData` 的任何内容都会作为 `session` 对象的一部分直接传递。

## 交接

与常规智能体类似，你可以使用交接将智能体拆分为多个智能体，并在它们之间编排，以提升智能体性能并更好地限定问题范围。

<Code lang="typescript" code={multiAgentsExample} />

与常规智能体不同，交接在实时智能体中会有些差异。执行交接时，正在进行的会话会更新为新的智能体配置。由于这一点，智能体会自动访问正在进行的对话历史，且当前不会应用输入过滤器。

此外，这意味着在交接过程中无法更改 `voice` 或 `model`。你也只能连接到其他实时智能体。如果你需要使用不同的模型，例如像 `gpt-5-mini` 这样的推理模型，你可以使用[通过工具进行委托](#delegation-through-tools)。

## 工具

与常规智能体一样，实时智能体可以调用工具来执行操作。你可以使用与常规智能体相同的 `tool()` 函数来定义工具。

<Code lang="typescript" code={defineToolExample} />

实时智能体只能使用函数工具，并且这些工具会在与你的 Realtime Session 相同的位置执行。这意味着如果你在浏览器中运行 Realtime Session，你的工具也会在浏览器中执行。如果需要执行更敏感的操作，你可以在工具内部向后端服务器发起 HTTP 请求。

在工具执行期间，智能体将无法处理来自用户的新请求。改进体验的一种方式是告知智能体在即将执行工具时进行提示，或说出特定短语以为工具执行争取时间。

### 访问对话历史

除了智能体调用特定工具时传入的参数外，你还可以访问由 Realtime Session 维护的当前对话历史快照。如果你需要基于对话的当前状态执行更复杂的操作，或计划[将工具用于委托](#delegation-through-tools)，这会很有用。

<Code lang="typescript" code={toolHistoryExample} />

<Aside type="note">
  传入的历史是工具调用当下的历史快照。用户最后一句话的转录可能尚不可用。
</Aside>

### 工具执行前的审批

如果将工具定义为 `needsApproval: true`，智能体会在执行工具前发出 `tool_approval_requested` 事件。

通过监听该事件，你可以向用户展示 UI 以批准或拒绝该次工具调用。

<Code lang="typescript" code={toolApprovalEventExample} />

<Aside type="note">
  当语音智能体在等待工具调用的审批时，智能体将无法处理来自用户的新请求。
</Aside>

## 护栏

护栏提供了一种方式来监控智能体的发言是否违反了一组规则，并立即切断响应。这些护栏检查基于智能体响应的转录进行，因此需要启用模型的文本输出（默认已启用）。

你提供的护栏会在模型返回响应的同时异步运行，允许你基于预定义的分类触发器来切断响应，例如“提到了特定的禁用词”。

当护栏被触发时，会话会发出 `guardrail_tripped` 事件。该事件还会提供一个包含触发护栏的 `itemId` 的 `details` 对象。

<Code lang="typescript" code={guardrailsExample} />

默认情况下，护栏会在每 100 个字符或响应文本生成结束时运行。由于朗读文本通常更耗时，这意味着在大多数情况下，护栏应能在用户听到之前捕获违规内容。

如果你想修改此行为，可以向会话传入一个 `outputGuardrailSettings` 对象。

<Code lang="typescript" code={guardrailSettingsExample} />

## 轮次检测 / 语音活动检测

Realtime Session 会使用 Realtime API 内置的[语音活动检测模式](https://platform.openai.com/docs/guides/realtime-vad)自动检测用户何时在说话，并据此触发新的轮次。

你可以通过向会话传入 `turnDetection` 对象来更改语音活动检测模式。

<Code lang="typescript" code={turnDetectionExample} />

修改轮次检测设置有助于校准意外的打断以及处理静音。查看[Realtime API 文档以了解不同设置的更多细节](https://platform.openai.com/docs/guides/realtime-vad)

## 打断

使用内置的语音活动检测时，用户打断智能体说话会自动触发智能体根据用户所说内容检测并更新上下文。同时会发出 `audio_interrupted` 事件。对于 WebSocket 连接，这可用于立刻停止所有音频播放。

<Code lang="typescript" code={audioInterruptedExample} />

如果你想执行手动打断，例如在 UI 中提供“停止”按钮，你可以手动调用 `interrupt()`：

<Code lang="typescript" code={sessionInterruptExample} />

无论哪种方式，Realtime Session 都会处理对智能体生成的打断、截断其对已对用户所述内容的认知，并更新历史。

如果你使用 WebRTC 连接到智能体，它还会清除音频输出。如果你使用 WebSocket，你需要自行停止已排队待播放内容的音频播放。

## 文本输入

如果你想向智能体发送文本输入，可以使用 `RealtimeSession` 上的 `sendMessage` 方法。

这在你希望让用户以双模态与智能体交互，或为对话提供额外上下文时很有用。

<Code lang="typescript" code={sendMessageExample} />

## 对话历史管理

`RealtimeSession` 会在 `history` 属性中自动管理对话历史：

你可以使用它向客户渲染历史或对其执行额外操作。由于在对话过程中此历史会不断变化，你可以监听 `history_updated` 事件。

如果你想修改历史，例如完全移除一条消息或更新其转录，你可以使用 `updateHistory` 方法。

<Code lang="typescript" code={updateHistoryExample} />

### 限制

1. 目前无法在事后更新/更改函数工具调用
2. 历史中的文本输出需要启用转录和文本模态
3. 因打断而被截断的响应没有转录

## 通过工具进行委托

![通过工具进行委托](https://cdn.openai.com/API/docs/diagram-speech-to-speech-agent-tools.png)

结合对话历史与一次工具调用，你可以将对话委托给另一个后端智能体来执行更复杂的操作，然后将结果传回给用户。

<Code lang="typescript" code={delegationAgentExample} />

下面的代码将在服务器上执行。本示例通过 Next.js 的 server actions 实现。

<Code lang="typescript" code={serverAgentExample} />
